package cc.linker.steplink.crm.service.impl;

import cc.linker.steplink.crm.commons.Constants;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.dao.*;
import cc.linker.steplink.crm.domain.*;
import cc.linker.steplink.crm.merchant.dao.PublicMenuDao;
import cc.linker.steplink.crm.merchanth5.dao.VipCustomerLogDao;
import cc.linker.steplink.crm.merchanth5.dao.WxShareDao;
import cc.linker.steplink.crm.merchanth5.service.SurvivalPushService;
import cc.linker.steplink.crm.response.GlobalException;
import cc.linker.steplink.crm.response.ResponseException;
import cc.linker.steplink.crm.service.EventMsgService;
import cc.linker.steplink.crm.service.PersonalService;
import com.mongodb.util.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static cc.linker.steplink.crm.merchanth5.controller.OverViewInfoController.INTERACTION;
import static cc.linker.steplink.crm.merchanth5.controller.OverViewInfoController.NEW_SUBSCRIBE;

@Slf4j
//@Service
public class EventMsgServiceImpl implements EventMsgService {
    @Autowired
    private EventMsgDao eventMsgDao;
    @Autowired
    private PersonalDao personalDao;
    @Autowired
    private PersonalService personalService;
    @Autowired
    private CustomerDao customerDao;
    @Autowired
    private CustomerInfoDao customerInfoDao;
    @Autowired
    private CustomerInfoWxDao customerInfoWxDao;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private HttpService httpService;
    @Autowired
    private ActionLogDao actionLogDao;
    @Autowired
    private WxShareDao wxShareDao;
    @Autowired
    private SurvivalPushService survivalPushService;
    @Autowired
    private PublicMenuDao publicMenuDao;
    @Autowired
    private VipCustomerLogDao vipCustomerLogDao;

    private final static String wxAction = "getWeixinUserInfo";

    @Override
    public void saveEvent(Map<String, Object> map) {
        /**
         * {
         *   "CreateTime": "1598323394",
         *   "token": "gh_2b949dcfd84a",
         *   "openId": "oQ9-51IlsnrWJ8y7Vqtpq4dm1ixs",
         *   "MsgType": "event",
         *   "EventType": "CLICK",
         *   "EventKey": "1295322872",
         *   "tag":"wxSystem"
         * }
         */
        if(!map.containsKey("tag")){
            //除微信矩阵其他系统调用不执行
            return;
        }
        LOGGER.info("saveEvent---------------->"+com.alibaba.fastjson.JSON.toJSONString(map));
        if (map.containsKey("token") && map.containsKey("openId")) {
            String token = (String) map.get("token");
            String openId = (String) map.get("openId");

            if ("unsubscribe".equals(map.get("EventType"))) {
                publicMenuDao.removeCancelAttentionCustomer(openId);
            }

            String orgId = eventMsgDao.getOrgIdByToken(token);
            String customerId = personalDao.getCustomerIdByOpenIdAndOrgId(openId, orgId);
            if (!StringUtils.isEmpty(customerId)) {
                //缓存用户互动
                String strNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
                redisTemplate.opsForSet().add(INTERACTION + strNow + "_" + orgId, customerId);
                redisTemplate.expire(INTERACTION + strNow + "_" + orgId,31,TimeUnit.DAYS);

                String key = INTERACTION + orgId + "_" +  customerId;
                redisTemplate.opsForValue().set(key, "1", 30, TimeUnit.DAYS);

                map.put("customerId", customerId);
                LocalDateTime dateTime = LocalDateTime.ofEpochSecond(Long.valueOf((String) map.get("CreateTime")), 0, ZoneOffset.ofHours(8));
                String s = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                map.put("CreateTime", s);
                Object eventKey = map.get("EventKey");
                if (!(eventKey instanceof String)) {
                    String serialize = JSON.serialize(eventKey);
                    map.put("EventKey", serialize);
                }
                eventMsgDao.saveEvent(map);
                Map<String, Object> sub = new HashMap<>();
                sub.put("customerId", customerId);
                if ("event".equals(map.get("MsgType"))) {

                    String menuKey = Constants.WXMenuKey.PUBLIC_MENU_TOKEN+token;
                    String menuSta = redisTemplate.opsForValue().get(menuKey);
                    if(!StringUtils.isEmpty(menuSta)){
                        if ("CLICK".equals(map.get("EventType")) && !map.get("EventKey").toString().startsWith("clickPushEvent*")) {
                            //菜单事件推送到mq
                            Map<String,Object> mqParam = new HashMap<>();
                            mqParam.put("customerId",customerId);
                            mqParam.put("eventTime",s);
                            mqParam.put("eventKey",map.get("EventKey"));
                            mqParam.put("token",map.get("token"));
                            mqParam.put("openId",map.get("openId"));
                        }
                    }

                    if ("subscribe".equals(map.get("EventType"))) {
//                        Map<String,Object> activeParams = new HashMap<>();
//                        activeParams.put("openId",openId);
//                        activeParams.put("token",token);
//                        activeParams.put("customerId",customerId);
//                        activeParams.put("action","subscribe");
//                        activeParams.put("orgId",orgId);
//                        activeParams.put("lastInteractionTime",null);
//                        wxShareDao.addcactivelog(activeParams);
//                        String logId = activeParams.get("logId").toString();
//                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                        String actionTime = sdf.format(new Date());
//                        survivalPushService.setPushSurvival(customerId,logId,"subscribe",actionTime,actionTime,orgId);

                        // 更新关注时间，取关后重新关注会覆盖时间
                        Action action = new Action();
                        action.setActionId(UUID.randomUUID().toString());
                        action.setActionFollowTime(new Date());
                        action.setCustomerId(customerId);
                        action.setOpenid(openId);
                        action.setToken(token);
                        actionLogDao.insertUpdateAction(action);

                        // 更新用户关注状态
                        sub.put("subscribe", 1);
                        customerDao.updateSubscribeByCustomerId(sub);
                        redisTemplate.opsForHash().increment(NEW_SUBSCRIBE, orgId, 1);

                        // 更新用户信息
                        WxUserInfoDto wxUserInfoDto;
                        Map<String, Object> params = new HashMap<>();
                        params.put("action", wxAction);
                        params.put("openid", openId);
                        params.put("token", token);
                        //获取微信用户信息
                        String result = null;
                        try {
                            result = httpService.doPost(systemProperties.getWxpushurl(), com.alibaba.fastjson.JSON.toJSONString(params));
                        } catch (URISyntaxException | IOException e) {
                            LOGGER.error("调用微信矩阵信息失败");
                            LOGGER.error("请求地址[{}]\n请求参数[{}]\n返回结果[{}]", systemProperties.getWxpushurl(), params, result);
                            throw GlobalException.build("获取用户信息异常");
                        }
                        if (StringUtils.isEmpty(result)) {
                            throw GlobalException.build("获取用户信息异常");
                        }
                        try {
                            wxUserInfoDto = com.alibaba.fastjson.JSON.parseObject(result, WxUserInfoDto.class);
                        } catch (Exception e) {
                            LOGGER.error("矩阵返回数据转为对象失败" + result, e);
                            throw GlobalException.build("获取用户信息异常");
                        }
                        if (wxUserInfoDto.getErrcode().equals("200")) {

                            WxUserInfo wxUserInfo = wxUserInfoDto.getData();
                            String area = "";
                            if (!StringUtils.isEmpty(wxUserInfo.getCountry()) && !"null".equals(wxUserInfo.getCountry())) {
                                area += wxUserInfo.getCountry();
                            }
                            area += "@";
                            if (!StringUtils.isEmpty(wxUserInfo.getProvince()) && !"null".equals(wxUserInfo.getProvince())) {
                                area += wxUserInfo.getProvince();
                            }
                            area += "@";
                            if (!StringUtils.isEmpty(wxUserInfo.getCity()) && !"null".equals(wxUserInfo.getCity())) {
                                area += wxUserInfo.getCity();
                            }

                            Customer customer = new Customer();
                            customer.setCustomerId(customerId);
                            customer.setCustomerName(wxUserInfo.getNickname());
                            customer.setCustomerAvatar(wxUserInfo.getHeadimgurl());
                            customerDao.updateByPrimaryKeySelective(customer);

                            //客户拓展信息
//                            CustomerInfo customerInfo = new CustomerInfo();
//                            customerInfo.setCustomerArea(area);
//                            customerInfo.setCustomerId(customerId);
//                            customerInfoDao.updateByCustomerIdSelective(customerInfo);

                            //客户微信信息
                            CustomerInfoWx customerInfoWx = new CustomerInfoWx();
                            if (wxUserInfo.getSex() != null) {
                                customerInfoWx.setWxGender(wxUserInfo.getSex().byteValue());
                            }
                            customerInfoWx.setWxAddress(area);
                            customerInfoWx.setWxName(wxUserInfo.getNickname());
                            customerInfoWx.setWxAvatar(wxUserInfo.getHeadimgurl());
                            customerInfoWx.setCustomerId(customerId);
                            customerInfoWxDao.updateByPrimaryKeySelective(customerInfoWx);
                        } else {
                            throw new GlobalException(new ResponseException(400, wxUserInfoDto.getMsg()));
                        }

                    } else if ("unsubscribe".equals(map.get("EventType"))) {
                        sub.put("subscribe", 0);
                        customerDao.updateSubscribeByCustomerId(sub);
                    }
                } else if ("text".equals(map.get("MsgType"))) {
                    // 记录用户对话行为
                    Action action = new Action();
                    action.setActionId(UUID.randomUUID().toString());
                    action.setActionTalkTime(new Date());
                    action.setCustomerId(customerId);
                    action.setOpenid(openId);
                    action.setToken(token);
                    actionLogDao.insertUpdateAction(action);
                }
            } else {
                if ("event".equals(map.get("MsgType"))) {
                    if ("subscribe".equals(map.get("EventType").toString())) {
                        //TODO 当前业务下globalOpenid和openId是同一个
                        personalService.saveWxH5User(openId, token, openId);
                        customerId = personalDao.getCustomerIdByOpenIdAndOrgId(openId, orgId);
                        redisTemplate.opsForHash().increment(NEW_SUBSCRIBE, orgId, 1);
                    }
                }
            }

            if ("subscribe".equals(map.get("EventType"))) {
                if (null != map.get("EventKey")) {
                    //关注事件取事件key值
                    String eventKeys = map.get("EventKey").toString();
                    eventKeys = eventKeys.replace("qrscene_","");
                    if (!eventKeys.equals(customerId)) {
                        survivalPushService.saveShareCache(eventKeys, "subscribe", orgId, customerId);
                    }
                }
            }

//            wxShareDao.setLastInteractionTime(customerId);
            if ("event".equals(map.get("MsgType"))) {
                if("SCAN".equals(map.get("EventType").toString()) || "subscribe".equals(map.get("EventType")) || ("CLICK".equals(map.get("EventType").toString()) && map.get("EventKey").toString().startsWith("clickPushEvent*"))){
                    Map<String,Object> activeParams = new HashMap<>();
                    activeParams.put("openId",openId);
                    activeParams.put("token",token);
                    activeParams.put("customerId",customerId);
                    activeParams.put("action",map.get("EventType"));
                    activeParams.put("orgId",orgId);
                    String eventKey = "";
                    if(null!=map.get("EventKey")){
                        eventKey = map.get("EventKey").toString();
                    }
                    activeParams.put("articleId",eventKey);
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String lastInteractionTime = sdf.format(new Date());
                    activeParams.put("lastInteractionTime",lastInteractionTime);
                    wxShareDao.addcactivelog(activeParams);
                }
            }
            //更新用户最后活跃时间
            wxShareDao.setCustomerLastInteraction(customerId);
            if (!"unsubscribe".equals(map.get("EventType"))) {
                this.setLastInteractionTime(customerId,map.get("EventKey")==null?null:map.get("EventKey").toString());
            }
        }
    }

    private void setLastInteractionTime(String customerId,String eventKey) {
        List<Map<String, Object>> activeLog = wxShareDao.getCustomerActiveLog(customerId);
        if(null != activeLog && activeLog.size()>0){
            for(Map<String, Object> al:activeLog){
                String orgId = al.get("orgId").toString();
                String logId = al.get("id").toString();
                String action = al.get("action").toString();
                String actionTime = al.get("actionTime").toString();
                String artId = "";
                if(!StringUtils.isEmpty(al.get("artId"))){
                    artId = al.get("artId").toString();
                }
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String lastInteractionTime = sdf.format(new Date());
                survivalPushService.setPushSurvival(customerId,logId,action,actionTime,lastInteractionTime,orgId,artId,eventKey);
            }
        }
    }

}
